home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 319.adf / CNewsSrc / uupc.lzh / vfprintf.c < prev    next >
C/C++ Source or Header  |  1990-02-06  |  5KB  |  199 lines

  1. /* Portable vfprintf and vprintf by Robert A. Larson <blarson@skat.usc.edu> */
  2.  
  3. /* Copyright 1989 Robert A. Larson.
  4.  * Distribution in any form is allowed as long as the author
  5.  * retains credit, changes are noted by their author, and the
  6.  * copyright message remains intact.  This program comes as-is
  7.  * with no warranty of fitness for any purpose.
  8.  *
  9.  * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
  10.  * the ANSI printf specs.
  11.  *
  12.  * Please send any bug fixes and improvements to blarson@skat.usc.edu .
  13.  * The use of goto is NOT a bug.
  14.  */
  15.  
  16. /* Feb    9, 1989        blarson        First usenet release */
  17.  
  18. /* This code implements the vfprintf function, without relying on
  19.  * the existance of _doprnt or other system specific code.
  20.  *
  21.  * Define NOVOID if (void *) is not a supported type.
  22.  *
  23.  * Two compile options are available for efficency:
  24.  *    INTSPRINTF    should be defined if sprintf is int and returns
  25.  *                the number of chacters formatted.
  26.  *    LONGINT        should be defined if sizeof(long) == sizeof(int)
  27.  *
  28.  * They only make the code smaller and faster, they need not be defined.
  29.  *
  30.  * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  31.  * than int in argument passing.  If this is defined, and LONGINT is not,
  32.  * the compiler must support the type unsigned long.
  33.  *
  34.  * Most quirks and bugs of the available fprintf fuction are duplicated,
  35.  * however "*" in the width and precision fields will work correctly
  36.  * even if fprintf does not support this.  The %n format and the return
  37.  * count will only work if fprintf returns the number of characters
  38.  * formatted.
  39.  *
  40.  * Bad format strings, or those with very long width and precision
  41.  * fields (including expanded * fields) will cause undesired results.
  42.  */
  43.  
  44. #define ULONGINT    unsigned long
  45.  
  46. #ifdef OSK        /* os9/68k can take advantage of both */
  47. #  define INTSPRINTF
  48. #  define LONGINT
  49. #  undef  ULONG
  50. #  define ULONG    unsigned int
  51. #endif /* OSK */
  52.  
  53. #ifdef MCH_AMIGA    /* Manx looks pretty much (!?) like Lattice */
  54. #  define    INTSPRINTF
  55. #  undef    ULONG
  56. #  define    ULONG    unsigned long
  57. #  if sizeof(long) == sizeof(int)
  58. #    define    LONGINT    /* Defined if (long) == (int) */
  59. #  endif
  60. #endif
  61.  
  62. #ifdef AMIGA        /* Lattice can take advantage of both */
  63. #  define INTSPRINTF
  64. #  if sizeof(long) == sizeof(int)
  65. #    define LONGINT
  66. #  endif
  67. #  undef  ULONG
  68. #  define ULONG    unsigned long
  69. #endif /* AMIGA */
  70.  
  71. #ifdef NOVOID
  72. typedef char *pointer;
  73. #else
  74. typedef void *pointer;
  75. #endif /* NOVOID */
  76.  
  77. #include <stdio.h>
  78.  
  79. #ifdef    INTSPRINTF
  80. #  define Sprintf(string,format,arg)    (sprintf((string),(format),(arg)))
  81. #else
  82. #  define Sprintf(string,format,arg)    (\
  83.     sprintf((string),(format),(arg)),\
  84.     strlen(string)\
  85. )
  86. #endif /* INTSPRINTF */
  87.  
  88. #ifdef __STDC__
  89. #  include <stdarg.h>
  90. #else
  91. #  include "varargs.h"
  92. #endif /* __STDC__ */
  93.  
  94. typedef int *intp;
  95.  
  96. int vfprintf(dest, format, args)
  97. FILE *dest;
  98. register char *format;
  99. va_list args;
  100. {
  101.     register char c;
  102.     register char *tp;
  103.     register int count = 0;
  104.     char tempfmt[64];
  105.  
  106.     tempfmt[0] = '%';
  107.     while (c = *format++) {
  108.         if (c == '%') {
  109.             tp = &tempfmt[1];
  110. continue_format:
  111.             switch(c = *format++) {
  112.             case 's':
  113.                 *tp++ = c;
  114.                 *tp = '\0';
  115.                 count += fprintf(dest, tempfmt, va_arg(args, char *));
  116.                 break;
  117.             case 'u':
  118.             case 'x':
  119.             case 'o':
  120.             case 'X':
  121.             case 'd':
  122.             case 'c':
  123.             case 'i':
  124.                 *tp++ = c;
  125.                 *tp = '\0';
  126. #ifndef LONGINT
  127.                 if (tempfmt[1] == 'l')
  128.                     count += fprintf(dest, tempfmt, va_arg(args, ULONG));
  129.                 else
  130. #endif /* LONGINT */
  131.                     count += fprintf(dest, tempfmt, va_arg(args, int));
  132.                 break;
  133.             case 'f':
  134.             case 'e':
  135.             case 'E':
  136.             case 'g':
  137.             case 'G':
  138.                 *tp++ = c;
  139.                 *tp = '\0';
  140.                 count += fprintf(dest, tempfmt, va_arg(args, double));
  141.                 break;
  142.             case 'p':
  143.                 *tp++ = c;
  144.                 *tp = '\0';
  145.                 count += fprintf(dest, tempfmt, va_arg(args, pointer));
  146.                 break;
  147.             case '-':
  148.             case '+':
  149.             case '0':
  150.             case '1':
  151.             case '2':
  152.             case '3':
  153.             case '4':
  154.             case '5':
  155.             case '6':
  156.             case '7':
  157.             case '8':
  158.             case '9':
  159.             case '.':
  160.             case ' ':
  161.             case '#':
  162.             case 'h':
  163. #ifndef LONGINT
  164.             case 'l':
  165.                 *tp++ = c;
  166.                 /* FALLTHROUGH */
  167. #else /* !LONGINT */
  168.                 *tp++ = c;
  169.                 /* FALLTHROUGH */
  170.             case 'l':
  171. #endif /* LONGINT */
  172.                 goto continue_format;
  173.             case '*':
  174.                 tp += Sprintf(tp, "%d", va_arg(args, int));
  175.                 goto continue_format;
  176.             case 'n':
  177.                 *va_arg(args, intp) = count;
  178.                 break;
  179.             case '%':
  180.             default:
  181.                 putc(c, dest);
  182.                 count++;
  183.                 break;
  184.             }
  185.         } else {
  186.             putc(c, dest);
  187.             count++;
  188.         }
  189.     }
  190.     return( count );
  191. }
  192.  
  193. vprintf(format, args)
  194. char *format;
  195. va_list args;
  196. {
  197.     return( vfprintf(stdout, format, args) );
  198. }
  199.